package com.caocaog.market.utils;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.caocaog.market.entity.ShopPrinter;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.jeecg.common.api.vo.Result;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


/**
 * 飞鹅打印机工具类
 *
 * @author chechen
 * @date 2021-12-20
 * @see <a href="http://www.feieyun.com/open/index.html">飞鹅开放平台</a>
 */
public class FePrinterUtil {

    private FePrinterUtil(){}

    /** 不需要修改 */
    private static final String URL = "https://api.feieyun.cn:443/Api/Open/";
    private static final String ERROR_MESSAGE = "飞鹅开放平台 api 无返回结果";

    /** 必填 账号名 */
    private static final String USER = "junyihe_100@163.com";
    /** 必填 飞鹅云后台注册账号后生成的UKEY 【备注：这不是填打印机的KEY】 */
    private static final String UKEY = "aRYgDN39p2hFMAfm";


    /**
     * 小票机打印订单
     *
     * @param orderInfo 要打印的订单信息
     * @param sn        打印机编号
     * @return 是否成功
     */
    public static String print(String orderInfo, String sn, int cascadeCount) {
        /*标签说明：
        单标签:
        "<BR>"为换行,"<CUT>"为切刀指令(主动切纸,仅限切刀打印机使用才有效果)
        "<LOGO>"为打印LOGO指令(前提是预先在机器内置LOGO图片),"<PLUGIN>"为钱箱或者外置音响指令
        成对标签：
        "<CB></CB>"为居中放大一倍,"<B></B>"为放大一倍,"<C></C>"为居中,<L></L>字体变高一倍
        <W></W>字体变宽一倍,"<QR></QR>"为二维码,"<BOLD></BOLD>"为字体加粗,"<RIGHT></RIGHT>"为右对齐
        拼凑订单内容时可参考如下格式
        根据打印纸张的宽度，自行调整内容的格式，可参考下面的样例格式*/

        List<NameValuePair> params = getParams();
        params.add(new BasicNameValuePair("apiname", "Open_printMsg"));
        params.add(new BasicNameValuePair("sn", sn));
        // 不能超过 5000 字节
        params.add(new BasicNameValuePair("content", orderInfo));
        params.add(new BasicNameValuePair("times", String.valueOf(cascadeCount)));

        return getErrorMessage(unifiedProcessingResult(params));
    }


    /**
     * 添加打印机（支持批量）
     *
     * @param shopPrinter 打印机信息
     * @return 是否成功
     */
    public static String addPrinter(ShopPrinter shopPrinter) {

        List<NameValuePair> params = getParams();
        params.add(new BasicNameValuePair("apiname", "Open_printerAddlist"));
        String format;
        System.out.println(shopPrinter.getSimNumber());
        if (StringUtils.isBlank(shopPrinter.getSimNumber())) {
            format = String.format("%s # %s # %s",
                    shopPrinter.getNumber(), shopPrinter.getPrinterKey(), shopPrinter.getName());
        } else {
            format = String.format("%s # %s # %s # %s",
                    shopPrinter.getNumber(), shopPrinter.getPrinterKey(), shopPrinter.getName(), shopPrinter.getSimNumber());
        }
        // 打印机编号(必填) # 打印机识别码(必填) # 备注名称(选填) # 流量卡号码(选填)，多台打印机请换行（\n）添加新打印机信息，每次最多100台。
        params.add(new BasicNameValuePair("printerContent", format));

        System.out.println(params);
        return getErrorMessage(unifiedProcessingResult(params));
    }

    /**
     * 更新打印机
     *
     * @param shopPrinter 打印机信息
     * @return 是否成功
     */
    public static String updatePrinter(ShopPrinter shopPrinter) {

        List<NameValuePair> params = getParams();
        params.add(new BasicNameValuePair("apiname", "Open_printerEdit"));
        params.add(new BasicNameValuePair("sn", shopPrinter.getNumber()));
        params.add(new BasicNameValuePair("name", shopPrinter.getName()));
        if (StringUtils.isNotBlank(shopPrinter.getSimNumber()))
            params.add(new BasicNameValuePair("phonenum", shopPrinter.getSimNumber()));

        return getErrorMessage(unifiedProcessingResult(params));
    }

    /**
     * 删除批量打印机
     *
     * @param snList 打印机编号，多台打印机请用减号“-”连接起来
     * @return 是否成功
     */
    public static String deletePrinter(String snList) {

        List<NameValuePair> params = getParams();
        params.add(new BasicNameValuePair("apiname", "Open_printerDelList"));
        params.add(new BasicNameValuePair("snlist", snList));

        return getErrorMessage(unifiedProcessingResult(params));
    }

    /**
     * 获取终端状态
     *
     * @param sn 打印机编号
     * @return 终端状态
     */
    public static Result<String> getStatus(String sn) {
        List<NameValuePair> params = getParams();
        params.add(new BasicNameValuePair("apiname", "Open_queryPrinterStatus"));
        params.add(new BasicNameValuePair("sn", sn));

        JSONObject resultJsonObject = unifiedProcessingResult(params);

        if (resultJsonObject == null) return Result.error(null, ERROR_MESSAGE);
        if (resultJsonObject.getInteger("ret") == 0) {
            return Result.OK(resultJsonObject.getString("data"));
        } else return Result.error(null, resultJsonObject.getString("msg"));

    }

    /**
     * 返回通用的请求参数
     *
     * @return 请求参数
     */
    private static List<NameValuePair> getParams() {
        String TIMESTAMP = String.valueOf(System.currentTimeMillis() / 1000);
        return new ArrayList<NameValuePair>() {{
            add(new BasicNameValuePair("user", USER));
            add(new BasicNameValuePair("stime", TIMESTAMP));
            add(new BasicNameValuePair("sig", DigestUtils.sha1Hex(USER + UKEY + TIMESTAMP)));
        }};
    }

    /**
     * 统一处理返回结果
     *
     * @return 是否成功
     */
    private static JSONObject unifiedProcessingResult(List<NameValuePair> params) {
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(30000)//读取超时
                .setConnectTimeout(30000)//连接超时
                .build();

        CloseableHttpClient httpClient = HttpClients.custom()
                .setDefaultRequestConfig(requestConfig)
                .build();
        HttpPost post = new HttpPost(URL);
        CloseableHttpResponse response = null;
        try {
            post.setEntity(new UrlEncodedFormEntity(params, "utf-8"));
            response = httpClient.execute(post);
            if (response.getStatusLine().getStatusCode() == 200) {
                HttpEntity httpentity = response.getEntity();
                if (httpentity != null) {
                    JSONObject resultJsonObject = JSONObject.parseObject(EntityUtils.toString(httpentity));
                    System.out.println(resultJsonObject);
                    return resultJsonObject;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                post.abort();
            } catch (Exception e) {
                e.printStackTrace();
            }
            try {
                httpClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    /**
     * 返回错误信息，如果返回结果正确则返回null
     *
     * @param resultJsonObject 请求接口的返回结果
     * @return 错误信息/null
     */
    private static String getErrorMessage(JSONObject resultJsonObject) {
        if (resultJsonObject == null) return ERROR_MESSAGE;
        if (resultJsonObject.getInteger("ret") == 0) {
            Object data = resultJsonObject.get("data");
            if (data instanceof JSONObject) {
                JSONArray errorList = ((JSONObject) data).getJSONArray("no");
                if (errorList.size() == 0) return null;
                else return errorList.getString(0);
            } else return (String) data;
        } else return resultJsonObject.getString("msg");
    }

}
